package com.syg.jvm;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

public class Hook {

    /**
     * .lock文件存放路径
     */
    private static final String LOCK_FILE_PATH = "./";

    /**
     * .lock文件名称
     */
    private static final String LOCK_FILE_NAME = ".lock_20211209";


    /**
     *
     * @param args
     */
    public static void main(String[] args) throws IOException, InterruptedException {
        // test1();
        test2();
    }

    /**
     *
     */
    public static void test2() throws IOException, InterruptedException {
        // 校验.lock文件是否存在
        checkLockFile();

        // 注入Hook线程
        addShutdownHook();

        for (;;) {
            TimeUnit.SECONDS.sleep(1);
            System.out.println("The program is running ...");

        }

    }

    private static void addShutdownHook() {
        Runtime.getRuntime().addShutdownHook(new Thread(()->{
            // 接受到了退出信号
            System.out.println("The program received kill signal..");
            // 删除.lock文件
            deleteLockFile();
        }));
    }

    /**
     * 校验.lock文件是否已经存在
     */
    private static void checkLockFile() throws IOException {
        if (isLockFileExisted()) {
            throw new RuntimeException("The program already running...");
        }

        // 不存在,则创建.lock文件
        createLockFile();
    }

    /**
     * .lock文件是否存在
     * @return
     */
    private static boolean isLockFileExisted() {
        File file = new File(LOCK_FILE_PATH + LOCK_FILE_NAME);
        return file.exists();
    }

    /**
     * 创建.lock文件
     */
    private static void createLockFile() throws IOException {
        File file = new File(LOCK_FILE_PATH + LOCK_FILE_NAME);
        boolean newFile = file.createNewFile();
    }

    private static void deleteLockFile(){
        File file = new File(LOCK_FILE_PATH + LOCK_FILE_NAME);
        file.delete();
    }

    /**
     * 当main线程退出时,钩子线程开始时运行
     */
    public static void test1() {
        // 为应用程序注入Hook(钩子)线程
        Runtime.getRuntime().addShutdownHook(new Thread(()->{
            System.out.println("The hook thread 1 is running ...");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("the hook thread 1 will exit ...");
        }));

        // 为应用程序注入Hook(钩子)线程
        Runtime.getRuntime().addShutdownHook(new Thread(()->{
            System.out.println("The hook thread 2 is running ...");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("the hook thread 2 will exit ...");
        }));

        System.out.println("the main thread will exit");
    }
}
